package com.ypj.rpc.transport.socket.client;

import com.ypj.rpc.entity.RpcRequest;
import com.ypj.rpc.entity.RpcResponse;
import com.ypj.rpc.enumeration.ResponseCode;
import com.ypj.rpc.enumeration.RpcError;
import com.ypj.rpc.exception.RpcException;
import com.ypj.rpc.loaderbalancer.LoaderBalancer;
import com.ypj.rpc.loaderbalancer.RandomLoadBalancer;
import com.ypj.rpc.registry.NacosServiceDiscovery;
import com.ypj.rpc.registry.NacosServiceRegistry;
import com.ypj.rpc.registry.ServiceDiscovery;
import com.ypj.rpc.registry.ServiceRegistry;
import com.ypj.rpc.serializer.CommonSerializer;
import com.ypj.rpc.serializer.KryoSerializer;
import com.ypj.rpc.transport.RpcClient;
import com.ypj.rpc.transport.socket.utils.ObjectReader;
import com.ypj.rpc.transport.socket.utils.ObjectWriter;
import com.ypj.rpc.utils.RpcMessageChecker;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * 实现发送的逻辑，将对象发送过去并接收返回对象
 */
@Slf4j
public class SocketClient implements RpcClient {

    private final ServiceDiscovery serviceDiscovery;

    private CommonSerializer serializer;

    public SocketClient() {
        this(new KryoSerializer(),new RandomLoadBalancer());
    }

    public SocketClient(CommonSerializer serializer) {
        this(serializer,new RandomLoadBalancer());
    }

    public SocketClient(LoaderBalancer balancer) {
        this(new KryoSerializer(),balancer);
    }

    public SocketClient(CommonSerializer serializer, LoaderBalancer balancer) {
        this.serializer = serializer;
        this.serviceDiscovery=new NacosServiceDiscovery(balancer);
    }

    @Override
    public Object sendRequest(RpcRequest rpcRequest) {
        if (serializer==null){
            log.error("未设置序列化器");
            throw new RpcException(RpcError.SERIALIZER_NOT_FOUND.getMessage());
        }
        InetSocketAddress inetSocketAddress= serviceDiscovery.lookup(rpcRequest.getInterfaceName());
        try(Socket socket=new Socket()){
            socket.connect(inetSocketAddress);
            OutputStream outputStream=socket.getOutputStream();
            InputStream inputStream=socket.getInputStream();
            ObjectWriter.writeObject(outputStream,rpcRequest,serializer);
            Object object = ObjectReader.readObject(inputStream);
            RpcResponse rpcResponse=(RpcResponse) object;
            if (rpcResponse==null){
                log.error("服务调用失败，service：{}",rpcRequest.getInterfaceName());
                throw new RpcException(RpcError.SERVICE_INVOCATION_FAILURE.getMessage());
            }
            if (rpcResponse.getStatusCode()==null||rpcResponse.getStatusCode()!= ResponseCode.SUCCESS.getCode()){
                log.error("服务调用失败，service：{}，response：{}",rpcRequest.getInterfaceName(),rpcResponse);
                throw new RpcException(RpcError.SERVICE_INVOCATION_FAILURE.getMessage());
            }
            RpcMessageChecker.check(rpcResponse,rpcRequest);
            return rpcResponse;
        } catch (IOException e) {
            log.error("调用服务失败：",e);
            throw new RpcException(RpcError.SERVICE_INVOCATION_FAILURE.getMessage());
        }
    }

}
